#ifndef LW_RANDOM_ACCESS_LIST_H
#define LW_RANDOM_ACCESS_LIST_H

#include <stdexcept>
#include <string>

#include "List.h"

/**
 * The base container for lists that provide random access.
 * (abstract)
 */
template<typename T>
class RandomAccessList : public List<T> {
protected:

public:

    virtual ~RandomAccessList() {
    }

    /**
     * Adds the specified element to the end of the list and returns the new list.
     */
    virtual inline List<T>& operator<<(const T& e) {
        Add(e); //@todo: typename?
        return *this;
    }

    /**
     * Appends the specified element to the end of this list.
     */
    virtual inline void Add(const T& e) {
        AddLast(e);
    }

    /**
     * Inserts the specified element at the specified position in this list.
     */
    virtual inline void Add(int index, const T& e) = 0;

    /**
     * Inserts the given element at the beginning of this list.
     */
    virtual inline void AddFirst(const T& e) = 0;

    /**
     * Inserts the given element at the end of this list.
     */
    virtual inline void AddLast(const T& e) = 0;

    /**
     * Returns true if this list contains the specified element.
     */
    virtual inline bool Contains(const T& e) const = 0;

    /**
     * Sets or returns the element at the specified position in this list.
     */
    virtual inline T& operator[](int index) = 0;

    /**
     * Returns the element at the specified position in this list.
     */
    virtual inline const T& operator[](int index) const = 0;

    /**
     * Replaces the element at the specified position in this list with the specified element.
     */
    virtual inline void Set(int index, const T& e) {
        (*this)[index] = e;
    }

    /**
     * Returns the element at the specified position in this list.
     */
    virtual inline const T& Get(int index) const {
        return (*this)[index];
    }

    /**
     * Returns the element at the specified position in this list.
     */
    virtual inline T& Get(int index) {
        return (*this)[index];
    }

    /**
     * Returns the first element in this list.
     */
    virtual inline const T& GetFirst() const = 0;

    /**
     * Returns the last element in this list.
     */
    virtual inline const T& GetLast() const = 0;

    /**
     * Returns the first element in this list.
     */
    virtual inline T& GetFirst() = 0;

    /**
     * Returns the last element in this list.
     */
    virtual inline T& GetLast() = 0;

    /**
     * Returns the index in this list of the first occurrence of the specified element, or -1 if the List does not contain this element.
     */
    virtual inline int IndexOf(const T& e) const = 0;

    /**
     * Returns the index in this list of the last occurrence of the specified element, or -1 if the list does not contain this element.
     */
    virtual inline int LastIndexOf(const T& e) const = 0;

    /**
     * Removes the element at the specified position in this list.
     */
    virtual inline void RemoveAt(int index) = 0;

    /**
     * Removes all occurrences of v from this list.
     */
    virtual inline void Remove(const T &v) = 0;

    /**
     * Removes the first element from this list.
     */
    virtual inline void RemoveFirst() = 0;

    /**
     * Removes the last element from this list.
     */
    virtual inline void RemoveLast() = 0;

};

#endif //LW_RANDOM_ACCESS_LIST_H
